package com.ly.mpayment.core.util;

import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.SystemDefaultHttpClient;
import org.apache.log4j.Logger;
import org.imgscalr.Scalr;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * Created by Administrator on 2016/6/24.
 */
public class FileUtils {
	static Logger logger = Logger.getLogger(FileUtils.class);
//	public static Properties server = null;

	/**
	 * the traditional io way
	 *
	 * @param filename
	 * @return
	 * @throws IOException
	 */
	public static byte[] fileToByteArrayByTraditionalWay(String filename) throws IOException {
		File f = new File(filename);
		if (!f.exists()) {
			throw new FileNotFoundException("找不到该图片");
		}
		ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length());
		BufferedInputStream in = null;
		try {
			in = new BufferedInputStream(new FileInputStream(f));
			int buf_size = 1024;
			byte[] buffer = new byte[buf_size];
			int len = 0;
			while (-1 != (len = in.read(buffer, 0, buf_size))) {
				bos.write(buffer, 0, len);
			}
			return bos.toByteArray();
		} finally {
			in.close();
			bos.close();
		}
	}

	/**
	 * NIO way
	 *
	 * @param filename
	 * @return
	 * @throws IOException
	 */
	public static byte[] fileToByteArrayByNIOWay(String filename) throws IOException {
		File f = new File(filename);
		// if (!f.exists()) {
		// throw new FileNotFoundException(filename);
		// }
		FileChannel channel = null;
		FileInputStream fs = null;
		try {
			fs = new FileInputStream(f);
			channel = fs.getChannel();
			ByteBuffer byteBuffer = ByteBuffer.allocate((int) channel.size());
			while ((channel.read(byteBuffer)) > 0) {
				// do nothing
				// System.out.println("reading");
			}
			return byteBuffer.array();
		} finally {
			try {
				channel.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				fs.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Mapped File way MappedByteBuffer 可以在处理大文件时，提升性能
	 *
	 * @param filename
	 * @return
	 * @throws IOException
	 */
	@SuppressWarnings("resource")
	public static byte[] fileToByteArrayByMappedFileWay(String filename) throws IOException {

		FileChannel fc = null;
		try {
			fc = new RandomAccessFile(filename, "r").getChannel();
			MappedByteBuffer byteBuffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()).load();
			System.out.println(byteBuffer.isLoaded());
			byte[] result = new byte[(int) fc.size()];
			if (byteBuffer.remaining() > 0) {
				// System.out.println("remain");
				byteBuffer.get(result, 0, byteBuffer.remaining());
			}
			return result;
		} catch (IOException e) {
			e.printStackTrace();
			throw e;
		} finally {
			try {
				fc.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 复制单个文件
	 *
	 * @param srcFileName
	 *            待复制的文件名
	 * @param destFileName
	 *            目标文件名
	 * @param overlay
	 *            如果目标文件存在，是否覆盖
	 * @return 如果复制成功返回true，否则返回false
	 */
	public static boolean copyFile(String srcFileName, String destFileName, boolean overlay) {
		File srcFile = new File(srcFileName);

		// 判断源文件是否存在
		if (!srcFile.exists()) {
			return false;
		} else if (!srcFile.isFile()) {
			return false;
		}

		// 判断目标文件是否存在
		File destFile = new File(destFileName);
		if (destFile.exists()) {
			// 如果目标文件存在并允许覆盖
			if (overlay) {
				// 删除已经存在的目标文件，无论目标文件是目录还是单个文件
				new File(destFileName).delete();
			}
		} else {
			// 如果目标文件所在目录不存在，则创建目录
			if (!destFile.getParentFile().exists()) {
				// 目标文件所在目录不存在
				if (!destFile.getParentFile().mkdirs()) {
					// 复制文件失败：创建目标文件所在目录失败
					return false;
				}
			}
		}

		// 复制文件
		int byteread = 0; // 读取的字节数
		InputStream in = null;
		OutputStream out = null;

		try {
			in = new FileInputStream(srcFile);
			out = new FileOutputStream(destFile);
			byte[] buffer = new byte[1024];

			while ((byteread = in.read(buffer)) != -1) {
				out.write(buffer, 0, byteread);
			}
			return true;
		} catch (FileNotFoundException e) {
			return false;
		} catch (IOException e) {
			return false;
		} finally {
			try {
				if (out != null)
					out.close();
				if (in != null)
					in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 获取类路径
	 * 
	 * @return
	 */
	public static String getRootPath() {
		String classPath = "";
		String rootPath = "";
		// windows
		if ("\\".equals(File.separator)) {
			classPath = FileUtils.class.getResource("/").getPath();
			rootPath = classPath.substring(1, classPath.lastIndexOf("/WEB-INF/classes/") + 17);
			rootPath = rootPath.replace("/", "\\") + "ffmpeg.exe";
		}
		// linux 创建软链接 可在任意目錄直接執行ffmpeg
		if ("/".equals(File.separator)) {
			// classPath =
			// FileUtils.class.getClass().getResource("/").getPath();
			// rootPath = classPath.substring(0,
			// classPath.lastIndexOf("/WEB-INF/classes/")+17);
			// rootPath = rootPath.replace("\\", "/")+"ffmpeg";
			rootPath = "ffmpeg";
		}
		return rootPath;
	}

	/**
	 * 检测文件是否存在 没有则创建文件
	 * 
	 * @Title isExist
	 * @Description TODO
	 * @param path
	 * @return
	 */
	public static boolean isExist(String path) {
		File file = new File(path);
		if (!file.exists()) {
			try {
				file.mkdirs();
				return true;
			} catch (Exception e) {
				logger.info(e);

			}
			return false;
		}
		return true;
	}

	/**
	 * 按时间生成文件名
	 * 
	 * @param fileName
	 * @return
	 */
	private static String getFileName(String fileName) {
		String returnFileName = null;
		Random random = new Random();
		int rnd = random.nextInt(100);
		// 拼接新的文件名
		returnFileName = System.currentTimeMillis() + "_" + rnd + "."
				+ fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
		return returnFileName;
	}

	/**
	 * 处理文件上传
	 *
	 * @param filePath
	 * @param fileName
	 * @param ins
	 * @param hasThumb
	 */
	@SuppressWarnings("unused")
	public static String handlerFileUpload(String filePath, String fileName, InputStream ins) {
		// 后期需要调整为配置文件
		File dir = new File(CookieRedis.get("ImagePath") + filePath);
		String returnFileName = null;
		Random random = new Random();
		int rnd = random.nextInt(100);
		// 拼接新的文件名
		returnFileName = System.currentTimeMillis() + "_" + rnd + "."
				+ fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
		if (!dir.exists()) {
			dir.mkdirs();
			logger.info("创建文件目录:" + dir.getPath());
		}
		// 存储原图

		String imgPath = dir.getPath() + "/" + returnFileName;
		File file = null;
		try {
			file = storeImg(imgPath, ins);
			// scp -r /var/chain/apache/htdocs/
			// root@182.150.6.37:/var/chain/apache/
		} catch (IOException e) {
			e.printStackTrace();
		}
		// if(file.length() > 51200){//大于50 kb图片需要生成缩率图
		// // 存储缩略图
		// ThumbGenerateThread thumbImgThread = new ThumbGenerateThread(imgPath,
		// dir.getPath());
		// // 线程处理图片缩放和存储
		// thumbImgThread.start();
		// }

		// if (type == 2) {// 视频
		// String ffmpegPath = FileUtils.getRootPath();
		// // System.out.println("----------------->:" + ffmpegPath);
		// if (ffmpegPath.contains("file:/")) {
		// ffmpegPath = ffmpegPath.replace("file:/", "");
		// }
		// imgPath = imgPath.replace("/", "\\");
		// ffmpegPath = ffmpegPath.replace("/", "\\");
		// FfmpegUtils ffmpeg = new FfmpegUtils(ffmpegPath);
		// thumbPath = imgPath.substring(0, imgPath.lastIndexOf("\\"));
		// // linux
		// if ("/".equals(File.separator)) {
		// imgPath = imgPath.replace("\\", "/");
		// thumbPath = thumbPath.replace("\\", "/");
		// ffmpeg.generateThumbnails(imgPath, new File(thumbPath), 280, 280, 1);
		// } else {
		// ffmpeg.generateThumbnails(imgPath, new File(thumbPath), 280, 280, 1);
		// }
		// }
		logger.info("图片路径:" + imgPath + "-->" + imgPath);
		return CookieRedis.get("server").concat(
				imgPath.replace("\\", "/").replace(CookieRedis.get("ImagePath").replace("\\", "/"), ""));
		// scpImageToServer(imgPath);
		// if (type == 2) {
		// thumbPath = thumbPath.replace("\\",
		// "/").replace(pro.getProperty("httpimage"), "");
		// String path = imgPath.replace("\\",
		// "/").replace(pro.getProperty("httpimage"), "");
		// return pro.getProperty("httpurl").concat(path).concat(";")
		// .concat(pro.getProperty("httpurl").concat(path.substring(0,
		// path.lastIndexOf("."))) + "-1.jpg");
		// } else {

		// }
	}

	/**
	 * 将流转换为图片，并存储到指定路径
	 *
	 * @param imgPath
	 *            图片存储路径
	 * @param ins
	 */
	private static File storeImg(String imgPath, InputStream ins) throws IOException {
		File file = new File(imgPath);
		File imgDir = new File(file.getParent());
		if (!imgDir.exists()) {
			imgDir.mkdirs();
		}
		OutputStream os = null;
		try {
			os = new FileOutputStream(file);
			int bytesRead = 0;
			byte[] buffer = new byte[1024];
			while ((bytesRead = ins.read(buffer)) != -1) {
				os.write(buffer, 0, bytesRead);
			}
		} finally {
			try {
				if (os != null) {
					os.close();
					ins.close();
				}
				return file;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	/**
	 * scp 到 图片备份服务器
	 * 
	 * @param filePath
	 */
	@SuppressWarnings("unused")
	private void scpImageToServer(String filePath) {
		String os = System.getProperty("os.name");
		if (!os.toLowerCase().startsWith("win")) {
			StringBuffer sb = new StringBuffer();
			if (!filePath.isEmpty()) {
				try {
					sb.append("scp ");
					sb.append(filePath);
					sb.append(" root@" + CookieRedis.get("imageIp") + ":");
					sb.append(filePath);
					Runtime.getRuntime().exec(sb.toString());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 * 
	 */
	public static void doGet(HttpServletRequest request, HttpServletResponse response, String fileUploadPath)
			throws ServletException, IOException {

		if (request.getParameter("getfile") != null && !request.getParameter("getfile").isEmpty()) {
			File file = new File(fileUploadPath, request.getParameter("getfile"));
			if (file.exists()) {
				int bytes = 0;
				ServletOutputStream op = response.getOutputStream();

				response.setContentType(getMimeType(file));
				response.setContentLength((int) file.length());
				response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");

				byte[] bbuf = new byte[1024];
				DataInputStream in = new DataInputStream(new FileInputStream(file));

				while ((in != null) && ((bytes = in.read(bbuf)) != -1)) {
					op.write(bbuf, 0, bytes);
				}

				in.close();
				op.flush();
				op.close();
			}
		} else if (request.getParameter("delfile") != null && !request.getParameter("delfile").isEmpty()) {
			File file = new File(fileUploadPath, request.getParameter("delfile"));
			if (file.exists()) {
				file.delete(); // TODO:check and report success
			}
		} else if (request.getParameter("getthumb") != null && !request.getParameter("getthumb").isEmpty()) {
			File file = new File(fileUploadPath, request.getParameter("getthumb"));
			if (file.exists()) {
				String mimetype = getMimeType(file);
				if (mimetype.endsWith("png") || mimetype.endsWith("jpeg") || mimetype.endsWith("gif")) {
					BufferedImage im = ImageIO.read(file);
					if (im != null) {
						BufferedImage thumb = Scalr.resize(im, 75);
						ByteArrayOutputStream os = new ByteArrayOutputStream();
						if (mimetype.endsWith("png")) {
							ImageIO.write(thumb, "PNG", os);
							response.setContentType("image/png");
						} else if (mimetype.endsWith("jpeg")) {
							ImageIO.write(thumb, "jpg", os);
							response.setContentType("image/jpeg");
						} else {
							ImageIO.write(thumb, "GIF", os);
							response.setContentType("image/gif");
						}
						ServletOutputStream srvos = response.getOutputStream();
						response.setContentLength(os.size());
						response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
						os.writeTo(srvos);
						srvos.flush();
						srvos.close();
					}
				}
			} // TODO: check and report success
		} else {
			PrintWriter writer = response.getWriter();
			writer.write("call POST with multipart form data");
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 * 
	 */
	public static void doPost(HttpServletRequest request, HttpServletResponse response, String fileUploadPath)
			throws ServletException, IOException {

		if (!ServletFileUpload.isMultipartContent(request)) {
			throw new IllegalArgumentException(
					"Request is not multipart, please 'multipart/form-data' enctype for your form.");
		}
		// SystemUser user = (SystemUser)
		// request.getSession().getAttribute("user");
		// if(user != null){
		// fileUploadPath.concat(user.getUseruuid().getId());
		// }

		ServletFileUpload uploadHandler = new ServletFileUpload(new DiskFileItemFactory());
		PrintWriter writer = response.getWriter();
		response.setContentType("application/json");
		JSONArray json = new JSONArray();
		try {
			List<FileItem> items = uploadHandler.parseRequest(request);
			for (FileItem item : items) {
				if (!item.isFormField()) {
					String fileName = getFileName(item.getName());
					File file = new File(fileUploadPath, fileName);
					if (!file.getParentFile().exists()) {
						file.getParentFile().mkdirs();
					}
					item.write(file);
					JSONObject jsono = new JSONObject();
					jsono.put("name", fileName);
					jsono.put("size", item.getSize());
					jsono.put("url", "upload?getfile=" + fileName);
					jsono.put("thumbnail_url", "upload?getthumb=" + fileName);
					jsono.put("delete_url", "upload?delfile=" + fileName);
					jsono.put("delete_type", "GET");
					jsono.put("path",
							CookieRedis.get("server").concat(file.getAbsolutePath().replace("\\", "/")
									.replace(CookieRedis.get("ImagePath").replace("\\", "/"), "")));
					json.add(jsono);
				}
			}
		} catch (FileUploadException e) {
			throw new RuntimeException(e);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			writer.write(json.toString());
			writer.close();
		}

	}

	private static String getMimeType(File file) {
		String mimetype = "";
		if (file.exists()) {
			// URLConnection uc = new URL("file://" +
			// file.getAbsolutePath()).openConnection();
			// String mimetype = uc.getContentType();
			// MimetypesFIleTypeMap gives PNG as application/octet-stream, but
			// it seems so does URLConnection
			// have to make dirty workaround
			if (getSuffix(file.getName()).equalsIgnoreCase("png")) {
				mimetype = "image/png";
			} else {
				javax.activation.MimetypesFileTypeMap mtMap = new javax.activation.MimetypesFileTypeMap();
				mimetype = mtMap.getContentType(file);
			}
		}
		System.out.println("mimetype: " + mimetype);
		return mimetype;
	}

	private static String getSuffix(String filename) {
		String suffix = "";
		int pos = filename.lastIndexOf('.');
		if (pos > 0 && pos < filename.length() - 1) {
			suffix = filename.substring(pos + 1);
		}
		System.out.println("suffix: " + suffix);
		return suffix;
	}

//	public static void refushParamerter(List<SysConfig> lists) {
//		server = new Properties();
//		if (lists != null && !lists.isEmpty()) {
//			for (SysConfig sys : lists) {
//				logger.info("SystemInit:" + sys.getAttr() + "," + sys.getAttrValue());
//				server.put(sys.getAttr(), sys.getAttrValue());
//			}
//		} else {
//			logger.info("SystemInit error");
//		}
//	}

	/**
	 * 删除文件，可以是文件或文件夹
	 *
	 * @param fileName
	 *            要删除的文件名
	 * @return 删除成功返回true，否则返回false
	 */
	public static boolean delete(String fileName) {
		File file = new File(fileName);
		if (!file.exists()) {
			System.out.println("删除文件失败:" + fileName + "不存在！");
			return false;
		} else {
			if (file.isFile())
				return deleteFile(fileName);
			else
				return deleteDirectory(fileName);
		}
	}

	/**
	 * 删除单个文件
	 *
	 * @param fileName
	 *            要删除的文件的文件名
	 * @return 单个文件删除成功返回true，否则返回false
	 */
	public static boolean deleteFile(String fileName) {
		File file = new File(fileName);
		// 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
		if (file.exists() && file.isFile()) {
			if (file.delete()) {
				System.out.println("删除单个文件" + fileName + "成功！");
				return true;
			} else {
				System.out.println("删除单个文件" + fileName + "失败！");
				return false;
			}
		} else {
			System.out.println("删除单个文件失败：" + fileName + "不存在！");
			return false;
		}
	}
	
	public static void deleteFileThread(String file){
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				FileUtils.deleteFile(file);
			}
		}).start();
	}
	
	

	/**
	 * 删除目录及目录下的文件
	 *
	 * @param dir
	 *            要删除的目录的文件路径
	 * @return 目录删除成功返回true，否则返回false
	 */
	public static boolean deleteDirectory(String dir) {
		// 如果dir不以文件分隔符结尾，自动添加文件分隔符
		if (!dir.endsWith(File.separator))
			dir = dir + File.separator;
		File dirFile = new File(dir);
		// 如果dir对应的文件不存在，或者不是一个目录，则退出
		if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
			System.out.println("删除目录失败：" + dir + "不存在！");
			return false;
		}
		boolean flag = true;
		// 删除文件夹中的所有文件包括子目录
		File[] files = dirFile.listFiles();
		for (int i = 0; i < files.length; i++) {
			// 删除子文件
			if (files[i].isFile()) {
				flag = deleteFile(files[i].getAbsolutePath());
				if (!flag)
					break;
			}
			// 删除子目录
			else if (files[i].isDirectory()) {
				flag = deleteDirectory(files[i].getAbsolutePath());
				if (!flag)
					break;
			}
		}
		if (!flag) {
			System.out.println("删除目录失败！");
			return false;
		}
		// 删除当前目录
		if (dirFile.delete()) {
			System.out.println("删除目录" + dir + "成功！");
			return true;
		} else {
			return false;
		}
	}
	
	
	public static String downloadFile(String url,Map<String, String> headers,String type) {
		File filepicF = null;
		DefaultHttpClient client = new SystemDefaultHttpClient();
		try {
			// 发送get请求
			HttpGet request = new HttpGet(url);
			if(headers != null){
				for(String key : headers.keySet()){
					request.setHeader(key, headers.get(key));
				}
			}
			HttpResponse response = client.execute(request);
			/** 请求发送成功，并得到响应 **/
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

				String picName = CookieRedis.get("exportPath");
				File filepic = new File(picName);
				if (!filepic.exists())
					filepic.mkdir();
				filepicF = new File(picName + new Date().getTime() + type);

				InputStream inputStream = response.getEntity().getContent();
				OutputStream outStream = new FileOutputStream(filepicF);
				IOUtils.copy(inputStream, outStream);
				outStream.close();
				client.getConnectionManager().shutdown();
				return filepicF.getAbsolutePath();
			}  
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			client.getConnectionManager().shutdown();
		}
		return null;
	}
}
